package lab5task2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 
 * Buffer class of circular buffer implementation using 
 *  java.util.concurrent ReentrantLock and Condition
 * 
 * @author Bulaev Igor
 *
 */

public class BoundedBuffer {

	private final ReentrantLock lock;
	private final Condition full;
	private final Condition empty;
	private char[] buffer;
	private final int size;
	private int in;
	private int out;
	private int count;

	public BoundedBuffer(int size) {
		lock = new ReentrantLock();
		empty = lock.newCondition();
		full = lock.newCondition();
		this.size = size;
		buffer = new char[size];
	}

	public void put(char c) throws InterruptedException {
		lock.lock();
		try {
			while (count == buffer.length) {
				full.await();
			}
			buffer[in] = c;
			in = (in + 1) % size;
			count++;
			empty.signalAll();
			} finally {
				System.out.println("Put " + in + ". Total: " + count);
				lock.unlock();
		}
	}

	public char take() throws InterruptedException {
		lock.lock();
		try {
			while (count == 0) {
				empty.await();
			}
			out = (out + 1) % size;
			count--;
			full.signalAll();
			return buffer[out];
		} finally {
			System.out.println("Taken " + out + ". Total: " + count);
			lock.unlock();
		}
	}

}
